#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
import os
import threading
import logging
import re
import asyncio
import time
from datetime import datetime


import db
import settings
from logger import set_logger

CONTENT_TYPE = 'blog'
TABLE_TYPE = db.Blog


def getitems(path='/root'):
    try:
        session = db.create_session()
        items = [item.dobule_to_dict() for item in session.query(
            TABLE_TYPE).filter_by(path=path).order_by(TABLE_TYPE.created_at.desc())]
        items.sort(key=lambda el: el['content_type'] != 'd')
    except BaseException as e:
        logging.error(e)
        items = []
    return {'items': items, 'path': path[1:].split('/')}


def getitems_(page=None, path='/root'):
    page = page if page is not None and isinstance(
        page, dict) else {'index': 1, 'size': 5}
    try:
        session = db.create_session()
        index = int(page.get('index', 1))
        size = int(page.get('size', 5))
        items = [item.dobule_to_dict() for item in session.query(TABLE_TYPE).filter_by(
            path=path).order_by(TABLE_TYPE.created_at.desc()).offset((index - 1) * size).limit(size)]
        total = len([item for item in session.query(
            TABLE_TYPE).filter_by(path=path)])
        total_page = (total - 1) // size + 1
        pre = False if index == 1 else True
        next_ = index < total_page
        page = {
            'index': index,
            'total': total,
            'total_page': total_page,
            'pre': pre, 'next': next_
        }
    except BaseException as e:
        logging.error(e)
        page = {
            'index': 1,
            'total': 0,
            'total_page': 0,
            'pre': False, 'next': False
        }
        items = []
    return {'items': items, 'page': page, 'path': path[1:].split('/')}


def get_item(fullpath):
    try:
        session = db.create_session()
        ppath, pname = fullpath.rsplit('/', 1)
        if len(ppath) <= 0:
            ppath = '/'
        item = session.query(TABLE_TYPE).filter_by(
            path=ppath, name=pname).first()
        if item.content_type == 'd':
            return {'status': False, 'msg': '路径[%s]不是文件' % fullpath}
        else:
            return {'status': True, 'msg': item.dobule_to_dict()}
    except BaseException as e:
        return {'status': False, 'msg': e}


def save_item(data, user_id=None):
    try:
        session = db.create_session()
        ppath, pname = data['path'].rsplit('/', 1)
        if len(ppath) <= 0:
            ppath = '/'
        else:
            mkdirs(ppath)
        item = session.query(TABLE_TYPE).filter_by(
            path=ppath, name=pname).first()
        if item and item != 'd':
            item.name = data['name']
            item.summary = data['summary']
            item.content = data['content']
            item.updated_at = datetime.now()
            item.updated_date = item.updated_at.strftime('%Y%m%d')
            item.updated_stamp = item.updated_at.timestamp()
        else:
            item = TABLE_TYPE(
                path=ppath, name=data['name'], summary=data['summary'], content=data['content'], content_type=CONTENT_TYPE)
            session.add(item)
        session.commit()
        return {'status': True, 'msg': '%s/%s' % (ppath, data['name'])}
    except BaseException as e:
        return {'status': False, 'msg': e}


def delete(fullpath, user_id=None):
    try:
        parent, name = fullpath.rsplit('/', 1)
        if len(parent) <= 0:
            return {'status': False, 'msg': '根路径[%s]不能删除' % fullpath}
        session = db.create_session()
        item = session.query(TABLE_TYPE).filter_by(
            path=parent, name=name).first()
        if item:
            if item.content_type == 'd':
                session.query(TABLE_TYPE).filter(TABLE_TYPE.path.like(
                    '%s/%s%%' % (item.path, item.name))).delete(synchronize_session=False)
            session.delete(item)
            session.commit()
            return {'status': True, 'msg': '删除[%s]成功' % fullpath}
        else:
            return {'status': False, 'msg': '路径[%s]不存在' % fullpath}
    except BaseException as e:
        return {'status': False, 'msg': e}


def item_export(fullpath):
    try:
        parent, name = fullpath.rsplit('/', 1)
        if len(parent) <= 0:
            parent = None
        session = db.create_session()
        item = session.query(TABLE_TYPE).filter_by(
            path=parent, name=name).first()
        if not item:
            return {'status': False, 'msg': '文件[%s/%s]不存在' % (parent, name)}
        result = []
        if item.content_type == 'd':
            items = [item for item in session.query(TABLE_TYPE).filter(TABLE_TYPE.path.like(
                '%s%%' % fullpath))]
            for item_ in items:
                result.append({'path': item_.path, 'name': item_.name, 'content_type': CONTENT_TYPE,
                               'user_id': item_.user_id, 'summary': item_.summary, 'content': item_.content})
        else:
            result.append({'path': item.path, 'name': item.name, 'content_type': CONTENT_TYPE,
                           'user_id': item.user_id, 'summary': item.summary, 'content': item.content})
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': result}


def mkdirs(fullpath):
    session = db.create_session()
    ppath, pname = fullpath.rsplit('/', 1)
    if len(ppath) > 0:
        itemitem = session.query(TABLE_TYPE).filter_by(
            name=pname, path=ppath).first()
        if itemitem:
            return
        mkdirs(ppath)
        itemitem = TABLE_TYPE(status=1, name=pname,
                              path=ppath, content_type='d')
        session.add(itemitem)
        session.commit()
    else:
        parent, name = (None, pname)
        itemitem = session.query(TABLE_TYPE).filter_by(
            name=name, path=parent).first()
        if itemitem:
            return


def item_import(data):
    additem = []
    try:
        session = db.create_session()
        paths = []
        fileitem_exists = []
        fileitem_not_exists = []
        logging.warning('data: %s' % data)
        for item in data:
            if not 'name' in item or not 'path' in item:
                logging.error('[--]文件[%s/%s]格式不正确: %s' %
                              (item['path'], item['name'], item))
                return {'status': False, 'msg': '[--]文件[%s/%s]格式不正确: %s' % (item['path'], item['name'], item)}
            item_ = session.query(TABLE_TYPE).filter_by(
                name=item['name'], path=item['path']).first()
            if item_:
                logging.warning('[-]文件[%s/%s]已存在' %
                                (item['path'], item['name']))
                fileitem_exists.append(item)
            else:
                fileitem_not_exists.append(item)
                if item['path'] in paths:
                    continue
                paths.append(item['path'])
        logging.warning('fileitem_exists: %s' % fileitem_exists)
        logging.warning('fileitem_not_exists: %s' % fileitem_not_exists)
        logging.warning('paths: %s' % paths)
        for path in paths:
            mkdirs(path)
        for item in fileitem_not_exists:
            # -1: 下载已暂停
            item_ = TABLE_TYPE(name=item.get('name', None), path=item.get('path', None), summary=item.get('summary', None), content=item.get(
                'content', None), user_id=item.get('user_id', None), content_type=CONTENT_TYPE)
            session.add(item_)
            session.commit()
            itemtmp = session.query(TABLE_TYPE).filter_by(
                name=item['name'], path=item['path']).first()
            additem.append(itemtmp)
    except BaseException as e:
        return {'status': False, 'msg': e}
    return {'status': True, 'msg': '导入%d数据' % len(additem)}


def set_item_status(fullpath, status):
    try:
        session = db.create_session()
        ppath, pname = fullpath.rsplit('/', 1)
        if len(ppath) <= 0:
            ppath = '/'
        item = session.query(TABLE_TYPE).filter_by(
            path=ppath, name=pname).first()
        if item:
            if item.content_type == 'd':
                return {'status': False, 'msg': '路径[%s]是文件夹' % fullpath}
            else:
                item.status = status
                item.updated_at = datetime.now()
                item.updated_date = item.updated_at.strftime('%Y%m%d')
                item.updated_stamp = item.updated_at.timestamp()
                session.commit()
                return {'status': True, 'msg': ppath}
        else:
            return {'status': False, 'msg': '路径[%s]不存在' % fullpath}
    except BaseException as e:
        return {'status': False, 'msg': e}


def makedir(parent, name, user_id=None):
    try:
        session = db.create_session()
        ppath, pname = parent.rsplit('/', 1)
        if len(ppath) <= 0:
            ppath = '/'
        if len([item for item in session.query(TABLE_TYPE).filter_by(path=ppath, name=pname, content_type='d')]) <= 0:
            return {'status': False, 'msg': '文件夹(%s)不存在' % parent}
        if len([item for item in session.query(TABLE_TYPE).filter_by(path=parent, name=name, content_type='d')]) > 0:
            return {'status': False, 'msg': '文件夹(%s/%s)已存在' % (parent, name)}
        item = TABLE_TYPE(name=name, path=parent,
                          user_id=user_id, content_type='d')
        session.add(item)
        session.commit()
        return {'status': True, 'msg': '%s/%s' % (parent, name)}
    except BaseException as e:
        return {'status': False, 'msg': e}


def move(fullpath, newpath):
    try:
        session = db.create_session()
        ppath, pname = newpath.rsplit('/', 1)
        if len(ppath) <= 0:
            ppath = '/'
        item = session.query(TABLE_TYPE).filter_by(
            path=ppath, name=pname).first()
        if item:
            if item.content_type != 'd':
                return {'status': False, 'msg': '目标路径[%s]不是文件夹' % newpath}
        else:
            return {'status': False, 'msg': '目标路径[%s]不存在' % newpath}

        ppath, pname = fullpath.rsplit('/', 1)
        if len(ppath) <= 0:
            return {'status': False, 'msg': '根目录[%s]不能移动' % fullpath}

        item = session.query(TABLE_TYPE).filter_by(
            path=newpath, name=pname).first()
        if item:
            return {'status': False, 'msg': '目标路径[%s]存在[%s同名文件' % (newpath, pname)}

        item = session.query(TABLE_TYPE).filter_by(
            path=ppath, name=pname).first()
        if item:
            if item.content_type == 'd':
                items = session.query(TABLE_TYPE).filter(
                    TABLE_TYPE.path.like('%s%%' % fullpath))
                if items:
                    for item_ in items:
                        item_.path = '%s/%s' % (newpath, pname)
                        item_.updated_at = datetime.now()
                        item_.updated_date = item_.updated_at.strftime(
                            '%Y%m%d')
                        item_.updated_stamp = item_.updated_at.timestamp()
            item.path = newpath
            item.updated_at = datetime.now()
            item.updated_date = item.updated_at.strftime('%Y%m%d')
            item.updated_stamp = item.updated_at.timestamp()
            session.commit()
            return {'status': True, 'msg': newpath}
        else:
            return {'status': False, 'msg': '路径[%s]不存在' % fullpath}
    except BaseException as e:
        return {'status': False, 'msg': e}


async def code():
    code = 'import datetime; print(datetime.datetime.now())'
    proc = await asyncio.create_subprocess_exec(
        sys.executable, '-c', code,
        stdout=asyncio.subprocess.PIPE)
    data = await proc.stdout.readline()
    line = data.decode('ascii').rstrip()
    await proc.wait()
    return line


async def exec(contnet):
    try:
        proc = await asyncio.create_subprocess_exec(
            sys.executable, '-c', contnet,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE)
        stdout, stderr = await proc.communicate()
        # result = f'[{contnet!r} exited with {proc.returncode}]\n\n'
        result = f'[exited with {proc.returncode}]\n\n'
        if stdout:
            result += f'[stdout]\n{stdout.decode()}'
        if stderr:
            result += f'[stderr]\n{stderr.decode()}'
        # data = await proc.stdout.read()
        # result = data.decode('utf-8').rstrip()
        await proc.wait()
        return {'status': True, 'msg': result}
    except BaseException as e:
        return {'status': False, 'msg': e}


if '__main__' == __name__:
    db.init_db('dev')
    print(getitems())
    # print(type(TABLE_TYPE))
